#include "stdafx.h"
#include "Framework.h"
#include "D3DWrap.h"

#include "../DXUT/dxstdafx.h"

extern HWND hWnd;
extern CFirstPersonCamera Camera;

// A structure for our custom vertex type
struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // The transformed position for the vertex
    DWORD color;        // The vertex color
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

TD3DWindow::TD3DWindow()
{
	// initialization
	pD3D = NULL;
	pD3DDevice = NULL;
	pVB = NULL;
}

HRESULT TD3DWindow::Create(HWND TargetWindow)
{
	// Copied from DX9 sample
	if ( (pD3D = Direct3DCreate9( D3D_SDK_VERSION )) == NULL ) 
		return E_FAIL;

    // Set up the structure used to create the D3DDevice. Most parameters are
    // zeroed out. We set Windowed to TRUE, since we want to do D3D in a
    // window, and then set the SwapEffect to "discard", which is the most
    // efficient method of presenting the back buffer to the display.  And 
    // we request a back buffer format that matches the current desktop display 
    // format.
    D3DPRESENT_PARAMETERS d3dpp; 
 //   ZeroMemory( &d3dpp, sizeof(d3dpp) );
 //   d3dpp.Windowed			= TRUE;
	//d3dpp.hDeviceWindow		= TargetWindow;
 //   d3dpp.SwapEffect		= D3DSWAPEFFECT_DISCARD;
 //   d3dpp.BackBufferFormat	= D3DFMT_UNKNOWN;

	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.BackBufferWidth			= DEFAULT_RWINDOW_WIDTH;
	d3dpp.BackBufferHeight			= DEFAULT_WINDOW_HEIGHT;
	d3dpp.BackBufferFormat			= D3DFMT_UNKNOWN;
	d3dpp.BackBufferCount			= 1;
	d3dpp.SwapEffect				= D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow				= TargetWindow;
	d3dpp.Windowed					= TRUE;

    // Create the Direct3D device. Here we are using the default adapter (most
    // systems only have one, unless they have multiple graphics hardware cards
    // installed) and requesting the HAL (which is saying we want the hardware
    // device rather than a software one). Software vertex processing is 
    // specified since we know it will work on all cards. On cards that support 
    // hardware vertex processing, though, we would see a big performance gain 
    // by specifying hardware vertex processing.
	HRESULT Result = pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, TargetWindow,
                                      D3DCREATE_HARDWARE_VERTEXPROCESSING,
                                      &d3dpp, &pD3DDevice );

    if( FAILED( Result ) )
    {
        return E_FAIL;
    }

	// Initialize VB
    CUSTOMVERTEX Vertices[] =
    {
        { 150.0f,  50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
        { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
        {  50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
    };

    // Create the vertex buffer. Here we are allocating enough memory
    // (from the default pool) to hold all our 3 custom Vertices. We also
    // specify the FVF, so the vertex buffer knows what data it contains.
    if( FAILED( pD3DDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
                                                 0, D3DFVF_CUSTOMVERTEX,
                                                 D3DPOOL_DEFAULT, &pVB, NULL ) ) )
    {
        return E_FAIL;
    }

    // Now we fill the vertex buffer. To do this, we need to Lock() the VB to
    // gain access to the Vertices. This mechanism is required becuase vertex
    // buffers may be in device memory.
    VOID* pVertices;
    if( FAILED( pVB->Lock( 0, sizeof(Vertices), (void**)&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, Vertices, sizeof(Vertices) );
    pVB->Unlock();

	return S_OK;
}

HRESULT TD3DWindow::Destroy()
{
	if (pVB != NULL)
		pVB->Release();

	if (pD3DDevice != NULL)
		pD3DDevice->Release();

	if (pD3D != NULL)
		pD3D->Release();

	return S_OK;
}

HRESULT TD3DWindow::Render()
{
	if (pD3DDevice == NULL)
		return E_FAIL;

	pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

    // Begin the scene
    if( SUCCEEDED( pD3DDevice->BeginScene() ) )
    {
        // Rendering of scene objects can happen here
		pD3DDevice->SetTransform( D3DTS_VIEW, Camera.GetViewMatrix() );
		pD3DDevice->SetTransform( D3DTS_PROJECTION, Camera.GetProjMatrix() );

        pD3DDevice->SetStreamSource( 0, pVB, 0, sizeof(CUSTOMVERTEX) );
        pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        pD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

        // End the scene
        pD3DDevice->EndScene();
    }

    // Present the backbuffer contents to the display
    pD3DDevice->Present( NULL, NULL, NULL, NULL );

	return S_OK;
}

HRESULT TD3DWindow::ScreenShotToTGA(TCHAR *FileName)
{
	return S_OK;
}